package Utils.web;

import Utils.io.IOUtils;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * TCP工具类
 *
 * @author d11yu
 */
public final class TcpUtils {

    //region clientSendMessageToServer

    /**
     * 客户端向服务器端发送字符串信息。
     *
     * @param msg  待发送的字符串信息
     * @param host 服务器端ip地址
     * @param port 服务器端口号
     */
    public static void clientSendMessageToServer(String msg, String host, int port) throws IOException {
        try (Socket socket = new Socket(InetAddress.getByName(host), port)) {
            clientSendMessageToServer(msg, socket);
        }
    }

    /**
     * 客户端向服务器端发送字符串信息。
     *
     * @param msg    待发送的字符串信息
     * @param socket 服务器端socket
     */
    public static void clientSendMessageToServer(String msg, Socket socket) throws IOException {
        endSendMessageToAnother(msg, socket);
    }
    //endregion

    //region clientSendFileToServer

    /**
     * 客户端向服务器端传输文件。
     *
     * @param path   待传输的文件路径
     * @param socket 服务器端socket
     * @throws IOException
     */
    public static void clientSendFileToServer(String path, Socket socket) throws IOException {
        File file = new File(path);
        clientSendFileToServer(file, socket);
    }

    /**
     * 客户端向服务器端传输文件。
     *
     * @param file   待传输的文件
     * @param socket 服务器端socket
     * @throws IOException
     */
    public static void clientSendFileToServer(File file, Socket socket) throws IOException {
        endSendFileToAnother(file, socket);
    }
    //endregion

    //region clientAcceptMessageFromServer

    /**
     * 客户端接收服务器端发送的字符串信息。
     *
     * @param socket
     * @return
     * @throws IOException
     */
    public static String clientAcceptMessageFromServer(Socket socket) throws IOException {
        return IOUtils.inputStream2String(socket.getInputStream());
    }
    //endregion

    //region serverAcceptMessageFromClient

    /**
     * 服务器端接收客户端传来的字符串信息。
     *
     * @param port 服务器端口号
     * @return 返回字符串信息
     */
    public static String serverAcceptMessageFromClient(int port) throws IOException {
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            return serverAcceptMessageFromClient(serverSocket);
        }
    }

    /**
     * 服务器端接收客户端传来的字符串信息。
     *
     * @return 返回字符串信息
     */
    public static String serverAcceptMessageFromClient(Socket socket) throws IOException {
        return IOUtils.inputStream2String(socket.getInputStream());
    }

    /**
     * 服务器端接收客户端传来的字符串信息。
     *
     * @param serverSocket 服务器端的serverSocket
     * @return 返回字符串信息
     */
    public static String serverAcceptMessageFromClient(ServerSocket serverSocket) throws IOException {
        return serverAcceptMessageFromClient(serverSocket.accept());
    }
    //endregion

    //region serverAcceptFileFromClient

    /**
     * 服务器端接收客户端发送的文件。
     *
     * @param port 服务器端的端口号
     * @param path 保存于服务器端的路径地址
     */
    public static void serverAcceptFileFromClient(int port, String path) throws IOException {
        try (ServerSocket serverSocket = new ServerSocket(port);
             Socket socket = serverSocket.accept()) {
            serverAcceptFileFromClient(socket, path);
        }
    }

    /**
     * 服务器端接收客户端发送的文件。
     *
     * @param socket 服务器端的socket
     * @param path   保存于服务器端的路径地址
     */
    public static void serverAcceptFileFromClient(Socket socket, String path) throws IOException {
        try (FileOutputStream fos = new FileOutputStream(path)) {
            IOUtils.inputStream2OutputStream(socket.getInputStream(), fos);
        }
    }
    //endregion


    //region serverSendDataToClient

    /**
     * 服务器端向客户端发送字符串信息。
     *
     * @param msg          待发送的信息
     * @param serverSocket 服务器端的serverSocket
     */
    public static void serverSendMessageToClient(String msg, ServerSocket serverSocket) throws IOException {
        try (Socket socket = serverSocket.accept()) {
            serverSendMessageToClient(msg, socket);
        }
    }

    /**
     * 服务器端向客户端发送字符串信息。
     *
     * @param msg    待发送的信息
     * @param socket 服务器端的socket
     */
    public static void serverSendMessageToClient(String msg, Socket socket) throws IOException {
        endSendMessageToAnother(msg, socket);
    }

    /**
     * 服务器端向客户端发送文件。
     *
     * @param file   待发送的文件
     * @param socket 服务器端的socket
     * @throws IOException
     */
    public static void serverSendFileToClient(File file, Socket socket) throws IOException {
        endSendFileToAnother(file, socket);
    }
    //endregion

    //region private methods

    /**
     * 一端向另一端发送字符串信息。
     *
     * @param msg    待发送的字符串信息
     * @param socket 服务器端socket
     */
    private static void endSendMessageToAnother(String msg, Socket socket) throws IOException {
        try (OutputStream os = socket.getOutputStream()) {
            os.write(msg.getBytes());
        }
    }

    /**
     * 一端向另一端发送文件。
     *
     * @param file   待发送的文件
     * @param socket 服务器端socket
     * @throws IOException
     */
    private static void endSendFileToAnother(File file, Socket socket) throws IOException {
        try (FileInputStream fis = new FileInputStream(file)) {
            IOUtils.inputStream2OutputStream(fis, socket.getOutputStream());
        }
    }
    //endregion
}
